﻿#include "myLabel.h"
#include <QMoveEvent>
#include <QPainter>
#include <QStyleOption>

myLabel::myLabel(QWidget* parent) :QLabel(parent)
{
    Init();
}

void myLabel::Init()
{
    m_XPtInterval = 0;
    m_YPtInterval = 0;
    m_ZoomValue = 1;
    m_Pressed = false;
    m_ScaleX = 1;
    m_ScaleY = 1;
    m_isFirstWheel = true;
    m_drawPoint = QPointF(0, 0);
}

void myLabel::setImage(QImage src)
{
    Init();
    m_ImageQ = src;
    this->update();
}

//鼠标按下
void myLabel::mousePressEvent(QMouseEvent* event)
{
    m_OldPos = event->pos();
    m_Pressed = true;
    m_mousePos = event->pos();
    emit signal_updataPos((convertLogicalDraw2Pixcel(convertMouse2LogicalDraw(m_mousePos))));

    //this->update();
}
//鼠标释放
void myLabel::mouseReleaseEvent(QMouseEvent* event)
{
    m_Pressed = false;
    if (event->button() == Qt::RightButton)
    {
        Init();
        update();
    }
}
//鼠标移动
void myLabel::mouseMoveEvent(QMouseEvent* event)
{
    if (m_Pressed)
    {
        this->setCursor(Qt::OpenHandCursor);
        QPoint pos = event->pos();
        int xPtInterval = pos.x() - m_OldPos.x();
        int yPtInterval = pos.y() - m_OldPos.y();
        m_XPtInterval += xPtInterval;
        m_YPtInterval += yPtInterval;
        m_drawPoint = QPointF(m_drawPoint.x() + xPtInterval, m_drawPoint.y() + yPtInterval);
        m_OldPos = pos;
    }
    this->update();
}
//当鼠标双击的时候
void myLabel::mouseDoubleClickEvent(QMouseEvent* event)
{

}

void myLabel::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);
    painter.setPen(QPen(Qt::red, 0));



    // 绘制样式
    if (m_ImageQ.isNull())
        return QWidget::paintEvent(event);

    // 根据窗口计算应该显示的图片的大小
    int row = this->height();
    int col = this->width();
    int srcRow = m_ImageQ.height();
    int srcCol = m_ImageQ.width();

    float width = qMin(m_ImageQ.width(), this->width());
    float height = width * 1.0 / (m_ImageQ.width() * 1.0 / m_ImageQ.height());
    height = qMin(height, (float)this->height());
    width = height * 1.0 * (m_ImageQ.width() * 1.0 / m_ImageQ.height());

    m_ScaleX = (float)width / m_ImageQ.width();
    m_ScaleY = (float)height / m_ImageQ.height(); // 当原始图像尺寸大于空间时，小于1，否则等于1
    m_ZoomDafault = m_ScaleX;
    //m_zoomValueOri = m_ScaleX;
    // 平移
    painter.translate(this->width() / 2 + m_XPtInterval, this->height() / 2 + m_YPtInterval);

    // 缩放比例求导数
	painter.scale(m_ZoomValue / m_ScaleX, m_ZoomValue / m_ScaleY);
	//painter.scale(m_ZoomValue , m_ZoomValue );

    // 绘制图像
    m_windowsPos = QRectF(- width/2.0, -height /2.0, width, height);
    painter.drawImage(m_windowsPos, m_ImageQ);


    if (m_ZoomValue > 32)
    {
        //绘制网格线
        QVector<QLineF> lines;
        m_xInDraw.clear();
        m_yInDraw.clear();

        for(int i =0; i < m_ImageQ.height(); i++)
        {
            auto ptDraw = convertPixcel2LogicalDraw(QPointF(0, i));
            auto ptMouse = convertLogicalDraw2Mouse(ptDraw);
            if (ptMouse.y() < 0 || ptMouse.y() > this->geometry().height()) continue;
            lines.push_back(QLineF(QPointF(-width / 2.0, ptDraw.y()),
              QPointF(width / 2, ptDraw.y())));
            m_yInDraw.push_back(ptDraw.y());
        }
        for (int j = 0; j < m_ImageQ.width(); j++)
        {
            auto ptDraw = convertPixcel2LogicalDraw(QPointF(j, 0));
            auto ptMouse = convertLogicalDraw2Mouse(ptDraw);
            if (ptMouse.x() < 0 || ptMouse.x() > this->geometry().width()) continue;
            lines.push_back(QLineF(QPointF(ptDraw.x(), -height / 2),
                QPointF(ptDraw.x(), height / 2)));
            m_xInDraw.push_back(ptDraw.x());
        }
        painter.drawLines(lines);

        // 绘制像素
        if (m_ZoomValue < 64) return;
        QVector<QPointF> ptPlotB;
        QVector<QPointF> ptPlotW;
        QVector<QString> m_msgW;
        QVector<QString> m_msgB;
        for (int i = 0; i < m_yInDraw.size(); i++)
        {
            for (int j = 0; j < m_xInDraw.size(); j++)
            {
                // 获取像素值及设置字体颜色
                auto ptPix = convertLogicalDraw2Pixcel(QPointF(m_xInDraw[j], m_yInDraw[i]));
                int x = (int)(ptPix.x() + 0.5);
                int y = (int)(ptPix.y() + 0.5);
                QColor color = QColor(m_ImageQ.pixel(x, y));
                int grey = 0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue();
                QString msg = QString("%1\n%2\n%3").arg(color.red()).arg(color.green()).arg(color.blue());

                if (grey < 128)
                {
                    m_msgB.push_back(msg);
                    ptPlotB.push_back(QPointF(m_xInDraw[j] * m_ZoomValue / m_ScaleX,
                        m_yInDraw[i] * m_ZoomValue / m_ScaleY));
                }
                else
                {
                    m_msgW.push_back(msg);
                    ptPlotW.push_back(QPointF(m_xInDraw[j] * m_ZoomValue / m_ScaleX,
                        m_yInDraw[i] * m_ZoomValue / m_ScaleY));
                }
            }
        }

        // 绘制
        QTextOption toption(Qt::AlignHCenter | Qt::AlignVCenter);//Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWrapAnywhere,
		// 设置自动换行模式
		toption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);

		// 反向写text时要用
        painter.scale(1.0 / m_ZoomValue * m_ScaleX, 1.0 / m_ZoomValue * m_ScaleY);
        painter.setPen(QPen(Qt::white, 0));
        for (int i = 0; i < ptPlotB.size(); i++)
        {
            painter.drawText(QRect(ptPlotB[i].x(), ptPlotB[i].y(), m_ZoomValue, m_ZoomValue),
                m_msgB[i], toption);
        }
        painter.setPen(QPen(Qt::black, 0));
        for (int i = 0; i < ptPlotW.size(); i++)
        {
            painter.drawText(QRect(ptPlotW[i].x(), ptPlotW[i].y(), m_ZoomValue, m_ZoomValue),
                m_msgW[i], toption);
        }
        //painter.scale(m_ZoomValue / m_ScaleX, m_ZoomValue / m_ScaleY);
    }
}
void myLabel::wheelEvent(QWheelEvent* event)
{
    int value = event->delta();
    m_mousePos = event->pos();
	auto tmp = convertLogicalDraw2Pixcel(convertMouse2LogicalDraw(m_mousePos));
	//auto tmp = convertLogicalDraw2Pixcel(m_mousePos);
    if (tmp.x() < 0 || tmp.x() > m_ImageQ.width() || tmp.y() < 0 || tmp.y() > m_ImageQ.height()) return;


    if (value > 0 && m_ZoomValue >= 500) return;
    if (value < 0 && m_ZoomValue < m_ZoomDafault)
    {
		//m_ZoomDafault = m_ZoomDafault;
        m_XPtInterval = 0;
        m_YPtInterval = 0;
        this->update();
        return;
    }

	//float m_zoomValueOri = m_ZoomValue;
	m_ZoomValue *= value > 0 ? 1.2 : 0.8;
	emit signal_updataZoom(m_ZoomValue);


    // 计算缩放后原始像素对应的界面坐标
    auto ptZoom = convertLogicalDraw2Mouse(convertPixcel2LogicalDraw(tmp));
    m_XPtInterval -= ptZoom.x() - m_mousePos.x();
    m_YPtInterval -= ptZoom.y() - m_mousePos.y();

    this->update();
}

void myLabel::onZoomInImage(void)
{
    m_ZoomValue *= 1.2;
    emit signal_updataZoom(m_ZoomValue);
    this->update();
}

void myLabel::onZoomOutImage(void)
{
    m_ZoomValue *= 0.8;
    if (m_ZoomValue <= 1)
    {
        m_ZoomValue += 1;
        emit signal_updataZoom(m_ZoomValue);

        return;
    }

    this->update();
}

QPointF myLabel::convertMouse2LogicalDraw(const QPointF& ptInMouse)
{
    auto lx = (ptInMouse.x() - this->width() / 2.0 - m_XPtInterval) / (m_ZoomValue / m_ScaleX);
    auto ly = (ptInMouse.y() - this->height() / 2.0 - m_YPtInterval) / (m_ZoomValue / m_ScaleY);

    return QPointF(lx, ly);
}

QPointF myLabel::convertLogicalDraw2Mouse(const QPointF& ptInDraw)
{
    auto lx = ptInDraw.x() * m_ZoomValue /m_ScaleX + m_XPtInterval + this->width() / 2.0;
    auto ly = ptInDraw.y() * m_ZoomValue / m_ScaleY + m_YPtInterval + this->height() / 2.0;

    return QPointF(lx, ly);
}

QPointF myLabel::convertLogicalDraw2Pixcel(const QPointF& ptInDraw)
{
    auto px = (ptInDraw.x() - m_windowsPos.x()) / m_ScaleX;
    auto py = (ptInDraw.y() - m_windowsPos.y()) / m_ScaleY;

    return QPointF(px, py);
}

QPointF myLabel::convertPixcel2LogicalDraw(const QPointF& ptInPixcel)
{
    auto px = ptInPixcel.x() * m_ScaleX + m_windowsPos.x();
    auto py = ptInPixcel.y() * m_ScaleY + m_windowsPos.y();

    return QPointF(px, py);
}